package com.yeskery.nut.extend.oauth;

import com.yeskery.nut.bean.NoSuchBeanException;
import com.yeskery.nut.core.*;
import com.yeskery.nut.extend.redis.JedisExecutor;
import com.yeskery.nut.extend.responsive.JsonResponsive;
import com.yeskery.nut.extend.responsive.JsonResponsivePlugin;
import com.yeskery.nut.plugin.PluginBeanMetadata;
import com.yeskery.nut.util.StringUtils;
import com.yeskery.nut.util.http.HttpUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * OAuth插件构造器
 * @author YESKERY
 * 2024/10/21
 */
public final class OAuthPluginBuilds {

    /**
     * 私有化构造器
     */
    private OAuthPluginBuilds(){
    }

    /**
     * 构建授权码模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param authorizeVerify 授权验证器
     * @param grantVerify 授权码模式授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @param authTokenValueHandler 授权令牌值处理器
     * @return 授权码模式服务器插件
     */
    public static OAuth2ServerPlugin buildAuthorizationCodeServerSessionPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                                               ClientAuthorizeVerify<AuthorizationCodeAuthorizeRequest> authorizeVerify,
                                                                               ClientCredentialsAuthorizeVerify<AuthorizationCodeGrantRequest> grantVerify,
                                                                               AuthorizeCodeAccessTokenResponseHandler<?> accessTokenResponseHandler,
                                                                               AuthTokenValueHandler authTokenValueHandler) {
        return buildAuthorizationCodeServerPlugin(authorizeForwardUri, authorizeForwardMethod, new SessionTokenStore(),
                -1, -1, -1, authorizeVerify, grantVerify, accessTokenResponseHandler, authTokenValueHandler);
    }

    /**
     * 构建授权码模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param jedisExecutor jedis执行器
     * @param codeExpires 授权码过期时间
     * @param accessExpires 访问令牌过期时间
     * @param refreshExpires 刷新令牌过期时间
     * @param authorizeVerify 授权验证器
     * @param grantVerify 授权码模式授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @param authTokenValueHandler 授权令牌值处理器
     * @return 授权码模式服务器插件
     */
    public static OAuth2ServerPlugin buildAuthorizationCodeServerJedisPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                                             JedisExecutor jedisExecutor, long codeExpires, long accessExpires, long refreshExpires,
                                                                             ClientAuthorizeVerify<AuthorizationCodeAuthorizeRequest> authorizeVerify,
                                                                             ClientCredentialsAuthorizeVerify<AuthorizationCodeGrantRequest> grantVerify,
                                                                             AuthorizeCodeAccessTokenResponseHandler<?> accessTokenResponseHandler,
                                                                             AuthTokenValueHandler authTokenValueHandler) {
        return buildAuthorizationCodeServerPlugin(authorizeForwardUri, authorizeForwardMethod, new JedisTokenStore(jedisExecutor),
                codeExpires, accessExpires, refreshExpires, authorizeVerify, grantVerify, accessTokenResponseHandler, authTokenValueHandler);
    }

    /**
     * 构建授权码模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param jedisExecutor jedis执行器
     * @param authorizeVerify 授权验证器
     * @param grantVerify 授权码模式授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @param authTokenValueHandler 授权令牌值处理器
     * @return 授权码模式服务器插件
     */
    public static OAuth2ServerPlugin buildAuthorizationCodeServerJedisPlugin(String authorizeForwardUri, Method authorizeForwardMethod, JedisExecutor jedisExecutor,
                                                                             ClientAuthorizeVerify<AuthorizationCodeAuthorizeRequest> authorizeVerify,
                                                                             ClientCredentialsAuthorizeVerify<AuthorizationCodeGrantRequest> grantVerify,
                                                                             AuthorizeCodeAccessTokenResponseHandler<?> accessTokenResponseHandler,
                                                                             AuthTokenValueHandler authTokenValueHandler) {
        return buildAuthorizationCodeServerPlugin(authorizeForwardUri, authorizeForwardMethod, new JedisTokenStore(jedisExecutor),
                5 * 60, 2 * 60 * 60, 7 * 24 * 60 * 60, authorizeVerify, grantVerify,
                accessTokenResponseHandler, authTokenValueHandler);
    }

    /**
     * 构建授权码模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param tokenStore 令牌存储
     * @param codeExpires 授权码过期时间
     * @param accessExpires 访问令牌过期时间
     * @param refreshExpires 刷新令牌过期时间
     * @param authorizeVerify 授权验证器
     * @param grantVerify 授权码模式授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @param authTokenValueHandler 授权令牌值处理器
     * @return 授权码模式服务器插件
     */
    public static OAuth2ServerPlugin buildAuthorizationCodeServerPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                                        TokenStore tokenStore, long codeExpires, long accessExpires, long refreshExpires,
                                                                        ClientAuthorizeVerify<AuthorizationCodeAuthorizeRequest> authorizeVerify,
                                                                        ClientCredentialsAuthorizeVerify<AuthorizationCodeGrantRequest> grantVerify,
                                                                        AuthorizeCodeAccessTokenResponseHandler<?> accessTokenResponseHandler,
                                                                        AuthTokenValueHandler authTokenValueHandler) {
        return buildAuthorizationCodeServerPlugin(authorizeForwardUri, authorizeForwardMethod, new SimpleAuthorizationCodeGenerator(tokenStore, codeExpires),
                new SimpleAccessTokenGenerator<>(tokenStore, accessExpires, refreshExpires),
                new RefreshAccessTokenGenerator<>(new SimpleAccessTokenGenerator<>(tokenStore, accessExpires, refreshExpires)),
                authorizeVerify, grantVerify, accessTokenResponseHandler, authTokenValueHandler);
    }

    /**
     * 构建授权码模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param authorizationCodeGenerator 授权码生成器
     * @param accessTokenGenerator 访问令牌生成器
     * @param refreshAccessTokenGenerator 刷新令牌生成器
     * @param authorizeVerify 授权验证器
     * @param grantVerify 授权码模式授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @param authTokenValueHandler 令牌值处理器
     * @return 授权码模式服务器插件
     */
    public static OAuth2ServerPlugin buildAuthorizationCodeServerPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                                        AuthorizationCodeGenerator authorizationCodeGenerator,
                                                                        AccessTokenGenerator<AuthorizationCodeGrantRequest> accessTokenGenerator,
                                                                        RefreshAccessTokenGenerator<RefreshTokenRequest> refreshAccessTokenGenerator,
                                                                        ClientAuthorizeVerify<AuthorizationCodeAuthorizeRequest> authorizeVerify,
                                                                        ClientCredentialsAuthorizeVerify<AuthorizationCodeGrantRequest> grantVerify,
                                                                        AuthorizeCodeAccessTokenResponseHandler<?> accessTokenResponseHandler,
                                                                        AuthTokenValueHandler authTokenValueHandler) {
        AuthorizationCodeServerConfiguration serverConfiguration = new AuthorizationCodeServerConfiguration();
        serverConfiguration.setAuthorizeForwardUri(authorizeForwardUri);
        serverConfiguration.setAuthorizeForwardMethod(authorizeForwardMethod);
        serverConfiguration.setAuthorizeVerify(authorizeVerify);
        serverConfiguration.setAuthorizationCodeGenerator(authorizationCodeGenerator);
        serverConfiguration.setGrantVerify(grantVerify);
        serverConfiguration.setAccessTokenGenerator(accessTokenGenerator);
        serverConfiguration.setRefreshAccessTokenGenerator(refreshAccessTokenGenerator);
        serverConfiguration.setRefreshVerify(t -> serverConfiguration.getRefreshAccessTokenGenerator().validateAccessToken(t.getRefreshToken()));
        serverConfiguration.setAccessTokenResponseHandler(accessTokenResponseHandler);
        serverConfiguration.setAuthTokenValueHandler(authTokenValueHandler);
        return buildAuthorizationCodeServerPlugin(serverConfiguration);
    }

    /**
     * 构建授权码模式服务器插件
     * @param serverConfiguration 授权码模式配置类
     * @return 授权码模式服务器插件
     */
    public static OAuth2ServerPlugin buildAuthorizationCodeServerPlugin(AuthorizationCodeServerConfiguration serverConfiguration) {
        if (StringUtils.isEmpty(serverConfiguration.getAuthorizeForwardUri())) {
            throw new IllegalArgumentException("Parameter[authorizeForwardUri] Must Not Be Empty.");
        } else if (serverConfiguration.getAuthorizeForwardMethod() == null) {
            throw new IllegalArgumentException("Parameter[authorizeForwardUri] Must Not Be Null.");
        } else if (serverConfiguration.getAuthorizeVerify() == null) {
            throw new IllegalArgumentException("Parameter[authorizeVerify] Must Not Be Null.");
        } else if (serverConfiguration.getAuthorizationCodeGenerator() == null) {
            throw new IllegalArgumentException("Parameter[authorizationCodeGenerator] Must Not Be Null.");
        } else if (serverConfiguration.getAccessTokenGenerator() == null) {
            throw new IllegalArgumentException("Parameter[accessTokenGenerator] Must Not Be Null.");
        } else if (serverConfiguration.getGrantVerify() == null) {
            throw new IllegalArgumentException("Parameter[grantVerify] Must Not Be Null.");
        } else if (serverConfiguration.getRefreshAccessTokenGenerator() == null) {
            throw new IllegalArgumentException("Parameter[refreshAccessTokenGenerator] Must Not Be Null.");
        } else if (serverConfiguration.getRefreshVerify() == null) {
            throw new IllegalArgumentException("Parameter[refreshVerify] Must Not Be Null.");
        }
        OAuth2ServerPlugin oAuth2ServerPlugin = new OAuth2ServerPlugin();
        oAuth2ServerPlugin.setControllerManagerConsumer(controllerManager -> {
            // 定义授权码模式请求
            controllerManager.registerController((request, response, execution) -> {
                String responseType = request.getParameter("response_type");
                if (!"code".equals(responseType)) {
                    throw new AuthorizationException("Server_Response_Type_Invalid", "Invalid Parameter[response_type]");
                }
                String redirectUri = request.getParameter("redirect_uri");
                if (StringUtils.isEmpty(redirectUri)) {
                    throw new AuthorizationException("Server_Redirect_Uri_Miss", "Invalid Parameter[redirect_uri]");
                }
                String clientId = request.getParameter("client_id");
                AuthorizationCodeAuthorizeRequest authorizeRequest = new AuthorizationCodeAuthorizeRequest();
                authorizeRequest.setResponseType(responseType);
                authorizeRequest.setClientId(clientId);
                authorizeRequest.setRedirectUri(request.getParameter("redirect_uri"));
                authorizeRequest.setScope(request.getParameter("scope"));
                if (StringUtils.isEmpty(clientId)) {
                    throw new AuthorizationException("Server_Client_Id_Miss", "Invalid Parameter[client_id]");
                } else if (!serverConfiguration.getAuthorizeVerify().verify(authorizeRequest)) {
                    throw new AuthorizationException("Server_Client_Id_Invalid", "Invalid Parameter[client_id]");
                }
                RequestApplicationContext.putResource(OAuth2ServerPlugin.AUTHORIZE_REQUEST_PARAMS_KEY, authorizeRequest);
                execution.getForward().forward(request, response, execution, serverConfiguration.getAuthorizeForwardUri(), serverConfiguration.getAuthorizeForwardMethod());
            }, serverConfiguration.getAuthorizeMethod(), serverConfiguration.getAuthorizeUri());
            // 定义授权码模式授权请求
            controllerManager.registerController((request, response, execution) -> {
                String grantType = request.getParameter("grant_type");
                if (!"authorization_code".equals(grantType)) {
                    throw new AuthorizationException("Server_Grant_Type_Invalid", "Invalid Parameter[grant_type]");
                }
                String clientId = request.getParameter("client_id");
                AuthorizationCodeGrantRequest grantRequest = new AuthorizationCodeGrantRequest();
                grantRequest.setGrantType(grantType);
                grantRequest.setClientId(clientId);
                grantRequest.setClientSecret(request.getParameter("client_secret"));
                grantRequest.setRedirectUri(request.getParameter("redirect_uri"));
                grantRequest.setCode(request.getParameter("code"));
                AuthorizationCodeGenerator authorizationCodeGenerator = serverConfiguration.getAuthorizationCodeGenerator();
                if (StringUtils.isEmpty(clientId) || StringUtils.isEmpty(grantRequest.getClientSecret()) || StringUtils.isEmpty(grantRequest.getCode())) {
                    throw new AuthorizationException("Server_Client_Credentials_Miss", "Miss Client Credentials");
                } else if (!authorizationCodeGenerator.validateAuthorizationCode(grantRequest.getCode())) {
                    throw new AuthorizationException("Server_Client_Authorization_Code_Invalid", "Invalid Client Authorization Code");
                } else if (!serverConfiguration.getGrantVerify().verify(grantRequest)) {
                    throw new AuthorizationException("Server_Client_Credentials_Invalid", "Invalid Client Credentials");
                }
                RequestApplicationContext.putResource(OAuth2ServerPlugin.AUTHORIZE_REQUEST_CODE_VALUE_KEY, authorizationCodeGenerator.getAuthorizationCodeValue(grantRequest.getCode()));
                AccessTokenResponse<Object> accessTokenResponse = serverConfiguration.getAccessTokenGenerator()
                        .generateAccessToken(grantRequest, serverConfiguration.getAuthTokenValueHandler());
                Optional.ofNullable(serverConfiguration.getAccessTokenResponseHandler()).ifPresent(r -> r.generateHandle(accessTokenResponse,
                        authorizationCodeGenerator.getAuthorizationCodeValue(grantRequest.getCode())));
                authorizationCodeGenerator.deleteAuthorizationCode(grantRequest.getCode());
                if (StringUtils.isEmpty(grantRequest.getRedirectUri())) {
                    response.writeJsonFromObject(accessTokenResponse);
                    return;
                }
                String responseBody;
                try {
                    JsonResponsive jsonResponsive = execution.getBindContext().getObject(JsonResponsive.class);
                    responseBody = jsonResponsive.getResponsiveConvert().convertTo(accessTokenResponse);
                } catch (NoSuchBeanException e) {
                    throw new NutException("OAuthPlugin Use JsonResponsive, Not Unable Find Plugin["
                            + JsonResponsivePlugin.class + "]", e);
                }
                HttpUtils.getDefaultInstance().doPost(grantRequest.getRedirectUri(), responseBody, MediaType.APPLICATION_JSON);
            }, serverConfiguration.getGrantMethod(), serverConfiguration.getGrantUri());
            // 定义授权码模式刷新请求
            controllerManager.registerController(getRefreshRequestHandler(serverConfiguration.getRefreshAccessTokenGenerator(),
                    serverConfiguration.getRefreshVerify(), serverConfiguration.getAccessTokenResponseHandler()),
                    serverConfiguration.getRefreshMethod(), serverConfiguration.getRefreshUri());
        });
        List<PluginBeanMetadata> pluginBeanMetadataList = new ArrayList<>(4);
        pluginBeanMetadataList.add(new PluginBeanMetadata("authorizationCodeGenerator",
                serverConfiguration.getAuthorizationCodeGenerator(), AuthorizationCodeGenerator.class));
        pluginBeanMetadataList.add(new PluginBeanMetadata("accessTokenGenerator",
                serverConfiguration.getAccessTokenGenerator(), AccessTokenGenerator.class));
        pluginBeanMetadataList.add(new PluginBeanMetadata("refreshAccessTokenGenerator",
                serverConfiguration.getRefreshAccessTokenGenerator(), RefreshAccessTokenGenerator.class));
        oAuth2ServerPlugin.setBindPluginBeanMetadata(pluginBeanMetadataList);
        return oAuth2ServerPlugin;
    }

    /**
     * 构建隐式模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param authorizeVerify 授权验证器
     * @return 隐式模式服务器插件
     */
    public static OAuth2ServerPlugin buildImplicitServerSessionPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                                      ClientAuthorizeVerify<ImplicitAuthorizeRequest> authorizeVerify) {
        return buildImplicitServerPlugin(authorizeForwardUri, authorizeForwardMethod, new SessionTokenStore(),
                -1, authorizeVerify);
    }

    /**
     * 构建隐式模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param jedisExecutor jedis执行器
     * @param accessExpires 访问令牌过期时间
     * @param authorizeVerify 授权验证器
     * @return 隐式模式服务器插件
     */
    public static OAuth2ServerPlugin buildImplicitServerJedisPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                                    JedisExecutor jedisExecutor, long accessExpires,
                                                                    ClientAuthorizeVerify<ImplicitAuthorizeRequest> authorizeVerify) {
        return buildImplicitServerPlugin(authorizeForwardUri, authorizeForwardMethod, new JedisTokenStore(jedisExecutor),
                accessExpires, authorizeVerify);
    }

    /**
     * 构建隐式模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param jedisExecutor jedis执行器
     * @param authorizeVerify 授权验证器
     * @return 隐式模式服务器插件
     */
    public static OAuth2ServerPlugin buildImplicitServerJedisPlugin(String authorizeForwardUri, Method authorizeForwardMethod, JedisExecutor jedisExecutor,
                                                                    ClientAuthorizeVerify<ImplicitAuthorizeRequest> authorizeVerify) {
        return buildImplicitServerPlugin(authorizeForwardUri, authorizeForwardMethod, new JedisTokenStore(jedisExecutor),
                15 * 60, authorizeVerify);
    }

    /**
     * 构建隐式模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param tokenStore 令牌存储
     * @param accessExpires 访问令牌过期时间
     * @param authorizeVerify 授权验证器
     * @return 隐式模式服务器插件
     */
    public static OAuth2ServerPlugin buildImplicitServerPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                               TokenStore tokenStore, long accessExpires,
                                                               ClientAuthorizeVerify<ImplicitAuthorizeRequest> authorizeVerify) {
        return buildImplicitServerPlugin(authorizeForwardUri, authorizeForwardMethod,
                new SimpleNoRefreshAccessTokenGenerator<>(tokenStore, accessExpires), authorizeVerify);
    }

    /**
     * 构建隐式模式服务器插件
     * @param authorizeForwardUri 授权页面跳转地址
     * @param authorizeForwardMethod 授权页面跳转方式
     * @param accessTokenGenerator 访问令牌生成器
     * @param authorizeVerify 授权验证器
     * @return 隐式模式服务器插件
     */
    public static OAuth2ServerPlugin buildImplicitServerPlugin(String authorizeForwardUri, Method authorizeForwardMethod,
                                                               AccessTokenGenerator<AuthorizationCodeGrantRequest> accessTokenGenerator,
                                                               ClientAuthorizeVerify<ImplicitAuthorizeRequest> authorizeVerify) {
        ImplicitServerConfiguration serverConfiguration = new ImplicitServerConfiguration();
        serverConfiguration.setAuthorizeForwardUri(authorizeForwardUri);
        serverConfiguration.setAuthorizeForwardMethod(authorizeForwardMethod);
        serverConfiguration.setAuthorizeVerify(authorizeVerify);
        serverConfiguration.setAccessTokenGenerator(accessTokenGenerator);
        return buildImplicitServerPlugin(serverConfiguration);
    }

    /**
     * 构建隐式模式服务器插件
     * @param serverConfiguration 服务器配置
     * @return 服务器插件
     */
    public static OAuth2ServerPlugin buildImplicitServerPlugin(ImplicitServerConfiguration serverConfiguration) {
        if (serverConfiguration.getAuthorizeVerify() == null) {
            throw new IllegalArgumentException("Parameter[authorizeVerify] Must Not Be Null.");
        } else if (serverConfiguration.getAccessTokenGenerator() == null) {
            throw new IllegalArgumentException("Parameter[accessTokenGenerator] Must Not Be Null.");
        }
        OAuth2ServerPlugin oAuth2ServerPlugin = new OAuth2ServerPlugin();
        oAuth2ServerPlugin.setControllerManagerConsumer(controllerManager -> {
            // 定义隐藏式模式请求
            controllerManager.registerController((request, response, execution) -> {
                String responseType = request.getParameter("response_type");
                if (!"token".equals(responseType)) {
                    throw new AuthorizationException("Server_Response_Type_Invalid", "Invalid Parameter[response_type]");
                }
                String redirectUri = request.getParameter("redirect_uri");
                if (StringUtils.isEmpty(redirectUri)) {
                    throw new AuthorizationException("Server_Redirect_Uri_Miss", "Invalid Parameter[redirect_uri]");
                }
                String clientId = request.getParameter("client_id");
                ImplicitAuthorizeRequest authorizeRequest = new ImplicitAuthorizeRequest();
                authorizeRequest.setResponseType(responseType);
                authorizeRequest.setClientId(clientId);
                authorizeRequest.setRedirectUri(request.getParameter("redirect_uri"));
                authorizeRequest.setScope(request.getParameter("scope"));
                if (StringUtils.isEmpty(clientId)) {
                    throw new AuthorizationException("Server_Client_Id_Miss", "Invalid Parameter[client_id]");
                } else if (!serverConfiguration.getAuthorizeVerify().verify(authorizeRequest)) {
                    throw new AuthorizationException("Server_Client_Credentials_Invalid", "Invalid Client Credentials");
                }
                request.addAttribute(OAuth2ServerPlugin.AUTHORIZE_REQUEST_PARAMS_KEY, authorizeRequest);
                execution.getForward().forward(request, response, execution, serverConfiguration.getAuthorizeForwardUri(), serverConfiguration.getAuthorizeForwardMethod());
            }, serverConfiguration.getAuthorizeMethod(), serverConfiguration.getAuthorizeUri());
        });
        List<PluginBeanMetadata> pluginBeanMetadataList = new ArrayList<>(2);
        pluginBeanMetadataList.add(new PluginBeanMetadata("accessTokenGenerator",
                serverConfiguration.getAccessTokenGenerator(), AccessTokenGenerator.class));
        oAuth2ServerPlugin.setBindPluginBeanMetadata(pluginBeanMetadataList);
        return oAuth2ServerPlugin;
    }

    /**
     * 构建密码模式服务器插件
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 密码模式服务器插件
     */
    public static OAuth2ServerPlugin buildPasswordServerSessionPlugin(ClientAuthorizeVerify<PasswordGrantRequest> authorizeVerify,
                                                                      AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildPasswordServerPlugin(new SessionTokenStore(), -1, -1, authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建密码模式服务器插件
     * @param jedisExecutor jedis执行器
     * @param accessExpires 访问令牌过期时间
     * @param refreshExpires 刷新令牌过期时间
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 密码模式服务器插件
     */
    public static OAuth2ServerPlugin buildPasswordServerJedisPlugin(JedisExecutor jedisExecutor, long accessExpires, long refreshExpires,
                                                                    ClientAuthorizeVerify<PasswordGrantRequest> authorizeVerify,
                                                                    AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildPasswordServerPlugin(new JedisTokenStore(jedisExecutor), accessExpires, refreshExpires, authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建密码模式服务器插件
     * @param jedisExecutor jedis执行器
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 密码模式服务器插件
     */
    public static OAuth2ServerPlugin buildPasswordServerJedisPlugin(JedisExecutor jedisExecutor, ClientAuthorizeVerify<PasswordGrantRequest> authorizeVerify,
                                                                    AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildPasswordServerPlugin(new JedisTokenStore(jedisExecutor),
                2 * 60 * 60, 7 * 24 * 60 * 60, authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建密码模式服务器插件
     * @param tokenStore 令牌存储
     * @param accessExpires 访问令牌过期时间
     * @param refreshExpires 刷新令牌过期时间
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 密码模式服务器插件
     */
    public static OAuth2ServerPlugin buildPasswordServerPlugin(TokenStore tokenStore, long accessExpires, long refreshExpires,
                                                               ClientAuthorizeVerify<PasswordGrantRequest> authorizeVerify,
                                                               AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildPasswordServerPlugin(new SimpleAccessTokenGenerator<>(tokenStore, accessExpires, refreshExpires),
                new RefreshAccessTokenGenerator<>(new SimpleAccessTokenGenerator<>(tokenStore, accessExpires, refreshExpires)),
                authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建密码模式服务器插件
     * @param accessTokenGenerator 访问令牌生成器
     * @param refreshAccessTokenGenerator 刷新令牌生成器
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 密码模式服务器插件
     */
    public static OAuth2ServerPlugin buildPasswordServerPlugin(AccessTokenGenerator<PasswordGrantRequest> accessTokenGenerator,
                                                               RefreshAccessTokenGenerator<RefreshTokenRequest> refreshAccessTokenGenerator,
                                                               ClientAuthorizeVerify<PasswordGrantRequest> authorizeVerify,
                                                               AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        PasswordServerConfiguration serverConfiguration = new PasswordServerConfiguration();
        serverConfiguration.setAuthorizeVerify(authorizeVerify);
        serverConfiguration.setAccessTokenGenerator(accessTokenGenerator);
        serverConfiguration.setRefreshAccessTokenGenerator(refreshAccessTokenGenerator);
        serverConfiguration.setRefreshVerify(t -> serverConfiguration.getRefreshAccessTokenGenerator().validateAccessToken(t.getRefreshToken()));
        serverConfiguration.setAccessTokenResponseHandler(accessTokenResponseHandler);
        return buildPasswordServerPlugin(serverConfiguration);
    }

    /**
     * 构建密码模式服务器插件
     * @param serverConfiguration 密码模式配置类
     * @return 密码模式服务器插件
     */
    public static OAuth2ServerPlugin buildPasswordServerPlugin(PasswordServerConfiguration serverConfiguration) {
        if (serverConfiguration.getAuthorizeVerify() == null) {
            throw new IllegalArgumentException("Parameter[authorizeVerify] Must Not Be Null.");
        } else if (serverConfiguration.getAccessTokenGenerator() == null) {
            throw new IllegalArgumentException("Parameter[accessTokenGenerator] Must Not Be Null.");
        } else if (serverConfiguration.getRefreshAccessTokenGenerator() == null) {
            throw new IllegalArgumentException("Parameter[refreshAccessTokenGenerator] Must Not Be Null.");
        } else if (serverConfiguration.getRefreshVerify() == null) {
            throw new IllegalArgumentException("Parameter[refreshVerify] Must Not Be Null.");
        }
        OAuth2ServerPlugin oAuth2ServerPlugin = new OAuth2ServerPlugin();
        oAuth2ServerPlugin.setControllerManagerConsumer(controllerManager -> {
            // 定义密码模式授权请求
            controllerManager.registerController((request, response, execution) -> {
                String grantType = request.getParameter("grant_type");
                if (!"password".equals(grantType)) {
                    throw new AuthorizationException("Server_Grant_Type_Invalid", "Invalid Parameter[grant_type]");
                }
                String username = request.getParameter("username");
                if (StringUtils.isEmpty(username)) {
                    throw new AuthorizationException("Server_Username_Miss", "Invalid Parameter[username]");
                }
                String password = request.getParameter("password");
                if (StringUtils.isEmpty(password)) {
                    throw new AuthorizationException("Server_Password_Miss", "Invalid Parameter[password]");
                }
                String clientId = request.getParameter("client_id");
                PasswordGrantRequest grantRequest = new PasswordGrantRequest();
                grantRequest.setGrantType(grantType);
                grantRequest.setClientId(clientId);
                grantRequest.setUsername(username);
                grantRequest.setPassword(password);
                if (StringUtils.isEmpty(clientId)) {
                    throw new AuthorizationException("Server_Client_Id_Miss", "Invalid Parameter[client_id]");
                } else if (!serverConfiguration.getAuthorizeVerify().verify(grantRequest)) {
                    throw new AuthorizationException("Server_Client_Credentials_Invalid", "Invalid Client Credentials");
                }
                AccessTokenResponse<Object> accessTokenResponse = serverConfiguration.getAccessTokenGenerator()
                        .generateAccessToken(grantRequest, serverConfiguration.getAuthTokenValueHandler());
                Optional.ofNullable(serverConfiguration.getAccessTokenResponseHandler()).ifPresent(r -> r.generateHandle(accessTokenResponse));
                response.writeJsonFromObject(accessTokenResponse);
            }, serverConfiguration.getGrantMethod(), serverConfiguration.getGrantUri());
            // 定义授权码模式刷新请求
            controllerManager.registerController(getRefreshRequestHandler(serverConfiguration.getRefreshAccessTokenGenerator(),
                            serverConfiguration.getRefreshVerify(), serverConfiguration.getAccessTokenResponseHandler()),
                    serverConfiguration.getRefreshMethod(), serverConfiguration.getRefreshUri());
        });
        List<PluginBeanMetadata> pluginBeanMetadataList = new ArrayList<>(2);
        pluginBeanMetadataList.add(new PluginBeanMetadata("accessTokenGenerator",
                serverConfiguration.getAccessTokenGenerator(), AccessTokenGenerator.class));
        pluginBeanMetadataList.add(new PluginBeanMetadata("refreshAccessTokenGenerator",
                serverConfiguration.getRefreshAccessTokenGenerator(), RefreshAccessTokenGenerator.class));
        oAuth2ServerPlugin.setBindPluginBeanMetadata(pluginBeanMetadataList);
        return oAuth2ServerPlugin;
    }

    /**
     * 构建凭证式服务器插件
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 凭证式服务器插件
     */
    public static OAuth2ServerPlugin buildClientCredentialsServerPlugin(ClientAuthorizeVerify<ClientCredentialsGrantRequest> authorizeVerify,
                                                                      AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildClientCredentialsServerPlugin(new SessionTokenStore(), -1, -1, authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建凭证式服务器插件
     * @param jedisExecutor jedis执行器
     * @param accessExpires 访问令牌过期时间
     * @param refreshExpires 刷新令牌过期时间
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 凭证式服务器插件
     */
    public static OAuth2ServerPlugin buildClientCredentialsServerPlugin(JedisExecutor jedisExecutor, long accessExpires, long refreshExpires,
                                                                    ClientAuthorizeVerify<ClientCredentialsGrantRequest> authorizeVerify,
                                                                    AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildClientCredentialsServerPlugin(new JedisTokenStore(jedisExecutor), accessExpires, refreshExpires, authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建凭证式服务器插件
     * @param jedisExecutor jedis执行器
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 凭证式服务器插件
     */
    public static OAuth2ServerPlugin buildClientCredentialsServerPlugin(JedisExecutor jedisExecutor, ClientAuthorizeVerify<ClientCredentialsGrantRequest> authorizeVerify,
                                                                    AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildClientCredentialsServerPlugin(new JedisTokenStore(jedisExecutor),
                2 * 60 * 60, 7 * 24 * 60 * 60, authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建凭证式服务器插件
     * @param tokenStore 令牌存储
     * @param accessExpires 访问令牌过期时间
     * @param refreshExpires 刷新令牌过期时间
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 凭证式服务器插件
     */
    public static OAuth2ServerPlugin buildClientCredentialsServerPlugin(TokenStore tokenStore, long accessExpires, long refreshExpires,
                                                               ClientAuthorizeVerify<ClientCredentialsGrantRequest> authorizeVerify,
                                                               AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        return buildClientCredentialsServerPlugin(new SimpleAccessTokenGenerator<>(tokenStore, accessExpires, refreshExpires),
                new RefreshAccessTokenGenerator<>(new SimpleAccessTokenGenerator<>(tokenStore, accessExpires, refreshExpires)),
                authorizeVerify, accessTokenResponseHandler);
    }

    /**
     * 构建凭证式服务器插件
     * @param accessTokenGenerator 访问令牌生成器
     * @param refreshAccessTokenGenerator 刷新令牌生成器
     * @param authorizeVerify 授权验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 凭证式服务器插件
     */
    public static OAuth2ServerPlugin buildClientCredentialsServerPlugin(AccessTokenGenerator<ClientCredentialsGrantRequest> accessTokenGenerator,
                                                               RefreshAccessTokenGenerator<RefreshTokenRequest> refreshAccessTokenGenerator,
                                                               ClientAuthorizeVerify<ClientCredentialsGrantRequest> authorizeVerify,
                                                               AccessTokenResponseHandler<?> accessTokenResponseHandler) {
        ClientCredentialsServerConfiguration serverConfiguration = new ClientCredentialsServerConfiguration();
        serverConfiguration.setAuthorizeVerify(authorizeVerify);
        serverConfiguration.setAccessTokenGenerator(accessTokenGenerator);
        serverConfiguration.setRefreshAccessTokenGenerator(refreshAccessTokenGenerator);
        serverConfiguration.setRefreshVerify(t -> serverConfiguration.getRefreshAccessTokenGenerator().validateAccessToken(t.getRefreshToken()));
        serverConfiguration.setAccessTokenResponseHandler(accessTokenResponseHandler);
        return buildClientCredentialsServerPlugin(serverConfiguration);
    }

    /**
     * 构建凭证式服务器插件
     * @param serverConfiguration 密码模式配置类
     * @return 密码模式服务器插件
     */
    public static OAuth2ServerPlugin buildClientCredentialsServerPlugin(ClientCredentialsServerConfiguration serverConfiguration) {
        if (serverConfiguration.getAuthorizeVerify() == null) {
            throw new IllegalArgumentException("Parameter[authorizeVerify] Must Not Be Null.");
        } else if (serverConfiguration.getAccessTokenGenerator() == null) {
            throw new IllegalArgumentException("Parameter[accessTokenGenerator] Must Not Be Null.");
        } else if (serverConfiguration.getRefreshAccessTokenGenerator() == null) {
            throw new IllegalArgumentException("Parameter[refreshAccessTokenGenerator] Must Not Be Null.");
        } else if (serverConfiguration.getRefreshVerify() == null) {
            throw new IllegalArgumentException("Parameter[refreshVerify] Must Not Be Null.");
        }
        OAuth2ServerPlugin oAuth2ServerPlugin = new OAuth2ServerPlugin();
        oAuth2ServerPlugin.setControllerManagerConsumer(controllerManager -> {
            // 定义密码模式授权请求
            controllerManager.registerController((request, response, execution) -> {
                String grantType = request.getParameter("grant_type");
                if (!"client_credentials".equals(grantType)) {
                    throw new AuthorizationException("Server_Grant_Type_Invalid", "Invalid Parameter[grant_type]");
                }
                String clientId = request.getParameter("client_id");
                if (StringUtils.isEmpty(clientId)) {
                    throw new AuthorizationException("Server_Client_Id_Miss", "Invalid Parameter[client_id]");
                }
                String clientSecret = request.getParameter("client_secret");
                if (StringUtils.isEmpty(clientSecret)) {
                    throw new AuthorizationException("Server_Client_Secret_Miss", "Invalid Parameter[client_secret]");
                }
                ClientCredentialsGrantRequest grantRequest = new ClientCredentialsGrantRequest();
                grantRequest.setGrantType(grantType);
                grantRequest.setClientId(clientId);
                grantRequest.setClientSecret(clientSecret);
                AccessTokenResponse<Object> accessTokenResponse = serverConfiguration.getAccessTokenGenerator()
                        .generateAccessToken(grantRequest, serverConfiguration.getAuthTokenValueHandler());
                Optional.ofNullable(serverConfiguration.getAccessTokenResponseHandler()).ifPresent(r -> r.generateHandle(accessTokenResponse));
                response.writeJsonFromObject(accessTokenResponse);
            }, serverConfiguration.getGrantMethod(), serverConfiguration.getGrantUri());
            // 定义授权码模式刷新请求
            controllerManager.registerController(getRefreshRequestHandler(serverConfiguration.getRefreshAccessTokenGenerator(),
                            serverConfiguration.getRefreshVerify(), serverConfiguration.getAccessTokenResponseHandler()),
                    serverConfiguration.getRefreshMethod(), serverConfiguration.getRefreshUri());
        });
        List<PluginBeanMetadata> pluginBeanMetadataList = new ArrayList<>(2);
        pluginBeanMetadataList.add(new PluginBeanMetadata("accessTokenGenerator",
                serverConfiguration.getAccessTokenGenerator(), AccessTokenGenerator.class));
        pluginBeanMetadataList.add(new PluginBeanMetadata("refreshAccessTokenGenerator",
                serverConfiguration.getRefreshAccessTokenGenerator(), RefreshAccessTokenGenerator.class));
        oAuth2ServerPlugin.setBindPluginBeanMetadata(pluginBeanMetadataList);
        return oAuth2ServerPlugin;
    }

    /**
     * 构建刷新令牌请求处理器
     * @param refreshAccessTokenGenerator 刷新令牌生成器
     * @param refreshVerify 刷新令牌验证器
     * @param accessTokenResponseHandler 访问令牌响应处理器
     * @return 刷新令牌请求处理器
     */
    private static RequestHandler getRefreshRequestHandler(RefreshAccessTokenGenerator<RefreshTokenRequest> refreshAccessTokenGenerator,
                                                           ClientCredentialsAuthorizeVerify<RefreshTokenRequest> refreshVerify,
                                                           AccessTokenResponseHandler<Object> accessTokenResponseHandler) {
        return (request, response, execution) -> {
            String grantType = request.getParameter("grant_type");
            if (!"refresh_token".equals(grantType)) {
                throw new AuthorizationException("Server_Grant_Type_Invalid", "Invalid Parameter[grant_type]");
            }
            String clientId = request.getParameter("client_id");
            RefreshTokenRequest refreshRequest = new RefreshTokenRequest();
            refreshRequest.setGrantType(grantType);
            refreshRequest.setClientId(clientId);
            refreshRequest.setClientSecret(request.getParameter("client_secret"));
            refreshRequest.setRefreshToken(request.getParameter("refresh_token"));
            if (StringUtils.isEmpty(clientId) || StringUtils.isEmpty(refreshRequest.getClientSecret()) || StringUtils.isEmpty(refreshRequest.getRefreshToken())) {
                throw new AuthorizationException("Server_Client_Credentials_Miss", "Miss Client Credentials");
            } else if (!refreshAccessTokenGenerator.validateAccessToken(refreshRequest.getRefreshToken())) {
                throw new AuthorizationException("Server_Client_Refresh_Access_Token_Invalid", "Invalid Client Refresh Access Token");
            } else if (!refreshVerify.verify(refreshRequest)) {
                throw new AuthorizationException("Server_Client_Credentials_Invalid", "Invalid Client Credentials");
            }
            AccessTokenResponse<Object> accessTokenResponse = refreshAccessTokenGenerator.generateAccessToken(refreshRequest);
            Optional.ofNullable(accessTokenResponseHandler).ifPresent(r -> r.refreshHandle(accessTokenResponse,
                    refreshAccessTokenGenerator.getAccessTokenValue(refreshRequest.getRefreshToken())));
            response.writeJsonFromObject(accessTokenResponse);
        };
    }
}
